/**
 * 将数组转换为Map对象
 * 
 * @template T 数组元素类型
 * @template K Map的键类型
 * @template V Map的值类型
 * @param {T[]} array 要转换的数组
 * @param {keyof T | ((item: T, index: number) => K)} keySelector 键选择器，可以是对象属性名或自定义函数
 * @param {((item: T, index: number) => V) | keyof T} [valueSelector] 值选择器，可以是对象属性名或自定义函数，默认为整个对象
 * @returns {Map<K, V>} 转换后的Map对象
 * 
 * @example
 * // 基本用法 - 使用对象属性作为键和值
 * const users = [
 *   { id: 1, name: '张三', age: 25 },
 *   { id: 2, name: '李四', age: 30 }
 * ];
 * const userMap = arrayToMap(users, 'id', 'name');
 * // Map(2) { 1 => '张三', 2 => '李四' }
 * 
 * @example
 * // 使用自定义函数作为键选择器
 * const items = ['apple', 'banana', 'orange'];
 * const itemMap = arrayToMap(items, 
 *   (item) => item.charAt(0), 
 *   (item) => item.length
 * );
 * // Map(3) { 'a' => 5, 'b' => 6, 'o' => 6 }
 */
export function arrayToMap<T, K, V>(
  array: T[],
  keySelector: keyof T | ((item: T, index: number) => K),
  valueSelector?: ((item: T, index: number) => V) | keyof T
): Map<K, V> {
  const map = new Map<K, V>();
  
  array.forEach((item, index) => {
    // 确定键
    const key = typeof keySelector === 'function'
      ? (keySelector as ((item: T, index: number) => K))(item, index)
      : item[keySelector] as unknown as K;
    
    // 确定值
    let value: V;
    if (valueSelector === undefined) {
      value = item as unknown as V;
    } else if (typeof valueSelector === 'function') {
      value = valueSelector(item, index);
    } else {
      value = item[valueSelector] as unknown as V;
    }
    
    map.set(key, value);
  });
  
  return map;
}

/**
 * 将数组转换为普通对象
 * 
 * @template T 数组元素类型
 * @template K 对象的键类型，必须是字符串、数字或符号
 * @template V 对象的值类型
 * @param {T[]} array 要转换的数组
 * @param {keyof T | ((item: T, index: number) => K)} keySelector 键选择器，可以是对象属性名或自定义函数
 * @param {((item: T, index: number) => V) | keyof T} [valueSelector] 值选择器，可以是对象属性名或自定义函数，默认为整个对象
 * @returns {Record<K, V>} 转换后的对象
 * 
 * @example
 * // 基本用法 - 使用对象属性作为键和值
 * const products = [
 *   { code: 'p001', name: '笔记本', price: 5999 },
 *   { code: 'p002', name: '键盘', price: 299 }
 * ];
 * const productObj = arrayToObject(products, 'code', 'price');
 * // { p001: 5999, p002: 299 }
 * 
 * @example
 * // 使用函数生成键和值
 * const cities = [
 *   { name: '北京', population: 21893095 },
 *   { name: '上海', population: 24870895 }
 * ];
 * const cityData = arrayToObject(
 *   cities,
 *   item => item.name.toLowerCase(),
 *   item => ({ pop: item.population, label: item.name })
 * );
 * // { 
 * //   '北京': { pop: 21893095, label: '北京' },
 * //   '上海': { pop: 24870895, label: '上海' }
 * // }
 */
export function arrayToObject<T, K extends string | number | symbol, V>(
  array: T[],
  keySelector: keyof T | ((item: T, index: number) => K),
  valueSelector?: ((item: T, index: number) => V) | keyof T
): Record<K, V> {
  const obj = {} as Record<K, V>;
  
  array.forEach((item, index) => {
    // 确定键
    const key = typeof keySelector === 'function'
      ? (keySelector as ((item: T, index: number) => K))(item, index)
      : item[keySelector] as unknown as K;
    
    // 确定值
    let value: V;
    if (valueSelector === undefined) {
      value = item as unknown as V;
    } else if (typeof valueSelector === 'function') {
      value = valueSelector(item, index);
    } else {
      value = item[valueSelector] as unknown as V;
    }
    
    obj[key] = value;
  });
  
  return obj;
}
